import { Breadcrumb, Button, message, Segmented } from 'antd';
import { cloneDeep } from 'lodash';
import React, { useCallback, useMemo, useState } from 'react';
import { OnConnectStartParams, useReactFlow, XYPosition } from 'reactflow';
import { useContextSelector } from 'use-context-selector';

import appService from '@/api/services/appService';
import mcpService from '@/api/services/mcpService';
import pluginService from '@/api/services/pluginService';
import { GetCreatedMcpListItem } from '@/common';
import { Empty, Input } from '@/components/eai-design';
import useWindowWidth from '@/hooks/event/use-window-width';
import { useScrollPagination } from '@/hooks/use-pagination/useVirtualScrollPagination';
import { useRequest2 } from '@/hooks/use-request';
import { useWorkflowUtils } from '@/hooks/use-workflow/useUtils';
import { t } from '@/locales/i18n';
import { WorkflowContext } from '@/pages/app/detail/components/Workflow/context';
import { getErrText } from '@/pages/chat/tools/utils';
import { useRouter } from '@/router/hooks';
import { useUserActions, useUserInfo } from '@/store/userStore';
import { useSystemStore } from '@/store/useSystemStore';
import {
  FlowNodeTemplateTypeEnum,
  FlowNodeTypeEnum,
  NodeInputKeyEnum,
  NodeOutputKeyEnum,
  workflowNodeTemplateList,
} from '@/types/workflow/constant';
import {
  NodeTemplateListItemType,
  NodeTemplateListType,
  ParentIdType,
} from '@/types/workflow/node';
import { moduleTemplatesFlat, localPluginModules } from '@/types/workflow/template/constants';
import { LoopEndNode } from '@/types/workflow/template/system/loop/loopEnd';
import { LoopStartNode } from '@/types/workflow/template/system/loop/loopStart';
import { nodeTemplate2FlowNode } from '@/utils/workflow/utils';

import EmptyTip from '../EmptyTip';
import { SvgIcon } from '../icon';
import MyTooltip from '../tooltip';

import './index.module.scss';

import AvatarDisplay from '../work-modal/components/AvatarDisplay';

import { MCPListType } from '@/types/workflow/mcp';

import { CircleLoading } from '../loading';

import { AppTypeEnum } from '@/types/app/type';
import { getNanoid } from '@/pages/chat/tools/tools';
import { FlowNodeInputItemType, FlowNodeOutputItemType } from '@/types/workflow/io';

// type ModuleTemplateListProps = {
//   onClose: () => void;
// };
type RenderListProps = {
  templates: NodeTemplateListItemType[];
  type: TemplateTypeEnum;
  // onClose: () => void;
  parentId: ParentIdType;
  setParentId: (parenId: ParentIdType) => any;
  connectParams?: OnConnectStartParams;
};

enum TemplateTypeEnum {
  'basic' = 'basic',
  'systemPlugin' = 'systemPlugin',
  'teamPlugin' = 'teamPlugin',
  'mcp' = 'mcp',
}

const sliderWidth = 240;

const renderTemplate = (
  template: NodeTemplateListItemType,
  type: TemplateTypeEnum,
  isPc: boolean,
  onAddNode: ({
    template,
    position,
    isDrag,
  }: {
    template: NodeTemplateListItemType;
    position: XYPosition;
    isDrag?: boolean;
  }) => void,
) => (
  <MyTooltip
    key={template.id}
    placement="right"
    title={
      <div>
        <div className="flex items-center">
          <AvatarDisplay
            src={
              type === TemplateTypeEnum.systemPlugin
                ? `${template.avatar!}.svg`
                : `${template.avatar!}`
            }
            className="h-[20px] max-h-[20px] w-[20px] max-w-[20px]"
            size={20}
          />
          <div className="ml-3 font-bold">{t(template.name as any)}</div>
        </div>
        <div className="mt-2">
          {template.intro ? t(template.intro as any) : t('core.workflow.Not intro')}
        </div>
      </div>
    }
  >
    <div
      className="flex cursor-pointer items-center justify-center rounded-md bg-fill-1 py-2 pl-2 hover:shadow-md"
      draggable={!template.isFolder}
      onDragEnd={(e) => {
        if (e.clientX < sliderWidth) return;
        onAddNode({
          template,
          position: { x: e.clientX, y: e.clientY },
          isDrag: true,
        });
      }}
      onClick={(e) => {
        // if (template.isFolder) {
        //   return setParentId(template.id);
        // }
        if (isPc) {
          return onAddNode({
            template,
            position: { x: window.innerWidth / 2 + sliderWidth + 140, y: 200 },
          });
        }
        onAddNode({
          template,
          position: { x: e.clientX, y: e.clientY },
        });
      }}
    >
      <div className="self-start rounded-lg bg-white p-2">
        <AvatarDisplay
          src={
            type === TemplateTypeEnum.systemPlugin
              ? `${template.avatar!}.svg`
              : `${template.avatar!}`
          }
          className="h-[16px] max-h-[16px] w-[16px] max-w-[16px]"
          size={16}
        />
      </div>
      <div className="ml-3 flex-1">
        <div className="line-clamp-1 flex-1 text-sm font-bold">{t(template.name as any)}</div>
      </div>
    </div>
  </MyTooltip>
);

const TeamPluginList: React.FC<{
  isPc: boolean;
  onAddNode: ({
    template,
    position,
    isDrag,
  }: {
    template: NodeTemplateListItemType;
    position: XYPosition;
    isDrag?: boolean;
  }) => void;
}> = ({ isPc, onAddNode }) => {
  const [searchText, setSearchText] = useState<string>('');
  const userInfo = useUserInfo();
  const { appId } = useContextSelector(WorkflowContext, (v) => v);
  const {
    data: pluginsList = [],
    isLoading: loading,
    ScrollData,
  } = useScrollPagination(pluginService.getTeamPluginList, {
    pageSize: 20,
    showLoadText: false,
    refreshDeps: [searchText],
    params: {
      searchText,
      appId,
    },
  });

  const plugins = useMemo(() => {
    const pluginTemplate = pluginsList.map((app) => {
      return {
        tmbId: app.tmbId,
        id: app.id || '',
        pluginId: app.id || '',
        isFolder:
          app.type === AppTypeEnum.folder ||
          app.type === AppTypeEnum.httpPlugin ||
          app.type === AppTypeEnum.toolSet,
        templateType: FlowNodeTemplateTypeEnum.teamApp,
        flowNodeType: (() => {
          if (app.type === AppTypeEnum.workflow) {
            return FlowNodeTypeEnum.appModule;
          }
          if (app.type === AppTypeEnum.toolSet) {
            return FlowNodeTypeEnum.toolSet;
          }
          return FlowNodeTypeEnum.pluginModule;
        })(),
        type: app.type,
        avatar: `${app.avatar}`,
        name: app.name,
        intro: app.intro,
        showStatus: false,
        version: app.pluginData?.nodeVersion || '481',
        isTool: true,
        createUserId: app.createUserId,
      };
    });

    // 区分我创建的和团队创建的
    const myPlugins = pluginTemplate.filter((plugin) => plugin.createUserId === userInfo._id);
    const teamPlugins = pluginTemplate.filter((plugin) => plugin.createUserId !== userInfo._id);
    return [
      {
        type: '官方插件',
        plugins: localPluginModules.filter((item) => item.name.includes(searchText)),
      },
      {
        type: '由我创建',
        plugins: myPlugins,
      },
      {
        type: '由他人创建',
        plugins: teamPlugins,
      },
    ];
  }, [pluginsList, searchText, userInfo._id]);

  const pluginCount = useMemo(() => {
    return plugins.reduce((acc, item) => acc + item.plugins.length, 0);
  }, [plugins]);

  return (
    <div className="flex h-[530px] w-[576px] overflow-hidden">
      <div className="w-full">
        <div className="mt-2">
          <div className="my-2">
            <Input
              placeholder="请输入内容"
              value={searchText}
              onChange={(e) => setSearchText(e.target.value)}
            />
          </div>
          {pluginCount > 0 && (
            <ScrollData className="h-[480px] overflow-y-auto overflow-x-hidden">
              <div className="flex flex-col gap-2 pr-2">
                {plugins
                  .filter((item) => item.plugins.length > 0)
                  .map((item) => (
                    <div key={item.type}>
                      <div className="flex">
                        <div className="mb-3 flex-1 text-sm text-gray-900">{item.type}</div>
                      </div>

                      <div className="grid grid-cols-3 gap-2">
                        {item.plugins.map((template) =>
                          renderTemplate(
                            template,
                            item.type === '官方插件'
                              ? TemplateTypeEnum.systemPlugin
                              : TemplateTypeEnum.teamPlugin,
                            isPc,
                            onAddNode,
                          ),
                        )}
                      </div>
                    </div>
                  ))}
              </div>
            </ScrollData>
          )}

          {pluginCount === 0 && (
            <div className="h-[480px] text-center">
              <Empty fontText="暂无插件" />
            </div>
          )}
        </div>
      </div>

      {loading && (
        <div className="absolute inset-0 flex items-center justify-center">
          <CircleLoading />
        </div>
      )}
    </div>
  );
};

const McpListRender = ({
  onAddNode,
}: {
  onAddNode: ({
    template,
    position,
    isDrag,
  }: {
    template: NodeTemplateListItemType;
    position: XYPosition;
    isDrag: boolean;
  }) => void;
}) => {
  const [searchText, setSearchText] = useState('');
  const [searchMcpText, setSearchMcpText] = useState('');
  const [currentMcp, setCurrentMcp] = useState<GetCreatedMcpListItem | undefined>(undefined);
  const {
    data: mcps = [],
    isLoading,
    ScrollData,
  } = useScrollPagination(mcpService.getMcpList, {
    pageSize: 10,
    showLoadText: false,
    refreshDeps: [searchText],
    params: {
      searchText,
    },
  });

  const getTeamPlugTemplates = useCallback(async () => {
    if (!currentMcp) {
      return [];
    }
    const res = await appService.getTeamPlugTemplates({ parentId: currentMcp.id });
    return res;
  }, [currentMcp]);

  const { data: mcpList = [], loading: isMcpListLoading } = useRequest2(getTeamPlugTemplates, {
    refreshDeps: [currentMcp],
    manual: false,
  });

  const formatMcps = useMemo<MCPListType>(() => {
    // 将mcps按照category分组，没有category归类为other
    if (!mcps || mcps.length === 0) {
      return [];
    }

    const groupedMcps: Record<string, GetCreatedMcpListItem[]> = {};

    mcps.forEach((mcp) => {
      // 获取第一个category，如果没有则归类为other
      const category = mcp.categoryCN ?? 'other';

      if (!groupedMcps[category]) {
        groupedMcps[category] = [];
      }

      groupedMcps[category].push(mcp);
    });

    // 转换为NodeTemplateListType格式
    return Object.entries(groupedMcps).map(([category, list]) => ({
      type: FlowNodeTemplateTypeEnum.tools,
      label: category,
      list,
    }));
  }, [mcps]);

  const addNode = useCallback(
    async (id: string, position: XYPosition, isDrag: boolean) => {
      const res = await pluginService.getPreviewPluginNode({ appId: id });
      if (res) {
        onAddNode({ template: res, position, isDrag });
      }
    },
    [onAddNode],
  );

  return (
    <div className="flex h-[530px] w-[576px] flex-col">
      {currentMcp ? (
        <div className="flex flex-col overflow-hidden">
          <div className="my-2">
            <Input
              placeholder="请输入内容"
              value={searchMcpText}
              onChange={(e) => setSearchMcpText(e.target.value)}
            />
          </div>
          <Breadcrumb separator="  /  " style={{ marginTop: '4px', marginBottom: '6px' }}>
            <Breadcrumb.Item
              className="cursor-pointer text-text-3"
              onClick={() => setCurrentMcp(undefined)}
            >
              MCP
            </Breadcrumb.Item>
            <Breadcrumb.Item className="cursor-pointer text-text-5">
              {currentMcp.name}
            </Breadcrumb.Item>
          </Breadcrumb>
          <div className="flex flex-1 flex-col gap-2 overflow-y-auto pr-2">
            {mcpList
              .filter((mcp) => mcp.name.toLowerCase().includes(searchMcpText.toLowerCase()))
              .map((mcp) => (
                <div
                  key={mcp.id}
                  className="flex cursor-pointer items-center rounded-md bg-fill-2 p-2"
                  onClick={(e) => {
                    addNode(
                      mcp.id,
                      { x: window.innerWidth / 2 + sliderWidth + 140, y: 200 },
                      false,
                    );
                  }}
                  draggable
                  onDragEnd={(e) => {
                    if (e.clientX < sliderWidth) return;
                    addNode(mcp.id, { x: e.clientX, y: e.clientY }, true);
                  }}
                >
                  <div className="ml-2">
                    <div
                      style={{ lineHeight: '22px' }}
                      className="text-sm font-font-weight-400 text-text-5"
                    >
                      {mcp.name}
                    </div>
                    <div
                      style={{ lineHeight: '20px' }}
                      className="text-xs font-font-weight-400 text-text-3"
                    >
                      {mcp.intro ?? t('core.workflow.Not intro')}
                    </div>
                  </div>
                </div>
              ))}
          </div>
        </div>
      ) : (
        <>
          <div className="my-2">
            <Input
              placeholder="请输入内容"
              value={searchText}
              onChange={(e) => setSearchText(e.target.value)}
            />
          </div>
          {formatMcps.length === 0 ? (
            <div className="flex h-full flex-1 items-center justify-center">
              <Empty />
            </div>
          ) : (
            <ScrollData className="h-[480px] overflow-y-auto overflow-x-hidden">
              <div className="w-full">
                {formatMcps.map((category, i) => (
                  <div key={category.label} className="mb-2">
                    {category.label && (
                      <div className="flex">
                        <div className="mb-3 mt-[6px] flex-1 text-sm text-gray-900">
                          {category.label}
                        </div>
                      </div>
                    )}

                    <div className="grid grid-cols-3 gap-2">
                      {category.list.map((template) => (
                        <MyTooltip
                          key={template.id}
                          placement="right"
                          title={
                            <div>
                              <div className="flex items-center">
                                <AvatarDisplay
                                  src={template.avatar!}
                                  className="h-[20px] max-h-[20px] w-[20px] max-w-[20px]"
                                  size={20}
                                />
                                <div className="ml-3 font-bold">{template.name}</div>
                              </div>
                              <div className="mt-2">
                                {template.description ?? t('core.workflow.Not intro')}
                              </div>
                            </div>
                          }
                        >
                          <div
                            className="group flex cursor-pointer items-center justify-center rounded-md bg-fill-1 py-2 pl-2 hover:shadow-md"
                            onClick={(e) => {
                              addNode(
                                template.id,
                                { x: window.innerWidth / 2 + sliderWidth + 140, y: 200 },
                                false,
                              );
                            }}
                            draggable
                            onDragEnd={(e) => {
                              if (e.clientX < sliderWidth) return;
                              addNode(template.id, { x: e.clientX, y: e.clientY }, true);
                            }}
                          >
                            <div className="self-start rounded-lg bg-white p-2">
                              <AvatarDisplay
                                src={template.avatar!}
                                className="h-[16px] max-h-[16px] w-[16px] max-w-[16px]"
                                size={16}
                              />
                            </div>
                            <div className="ml-3 flex-1">
                              <div className="line-clamp-1 flex-1 text-sm font-bold">
                                {template.name}
                              </div>
                            </div>
                            <Button
                              className="opacity-0 group-hover:opacity-100"
                              type="text"
                              onClick={(e) => {
                                e.stopPropagation();
                                setCurrentMcp(template);
                              }}
                              icon={<SvgIcon icon="arrow-right" color="var(--text-5)" />}
                            />
                          </div>
                        </MyTooltip>
                      ))}
                    </div>
                  </div>
                ))}
              </div>
            </ScrollData>
          )}
        </>
      )}
      {(isMcpListLoading || isLoading) && (
        <div className="absolute inset-0 flex items-center justify-center">
          <CircleLoading />
        </div>
      )}
    </div>
  );
};

// 提取renderBasic函数到组件外部
const renderBasicContent = (
  type: TemplateTypeEnum,
  formatTemplates: NodeTemplateListType,
  isPc: boolean,
  onAddNode: ({
    template,
    position,
    isDrag,
  }: {
    template: NodeTemplateListItemType;
    position: XYPosition;
    isDrag?: boolean;
  }) => void,
) => {
  return (
    <div className="flex h-[530px] w-[576px] overflow-auto">
      <div className={`${type === TemplateTypeEnum.teamPlugin ? '' : 'mt-2'} w-full`}>
        {formatTemplates.map((item, i) => (
          <div key={item.type} className="mb-2">
            {item.label && formatTemplates.length > 1 && (
              <div className="flex">
                <div className="mb-3 ml-2 flex-1 text-sm text-gray-900">{t(item.label as any)}</div>
              </div>
            )}

            <div className="grid grid-cols-3 gap-2">
              {item.list.map((template) => renderTemplate(template, type, isPc, onAddNode))}
            </div>
          </div>
        ))}
      </div>
    </div>
  );
};

const NodeTemplatesModal = ({ connectParams }: { connectParams?: OnConnectStartParams }) => {
  const router = useRouter();
  const { loadAndGetTeamMembers } = useUserActions();

  const [parentId, setParentId] = useState<ParentIdType>('');
  const [searchKey, setSearchKey] = useState('');
  const { basicNodeTemplates, hasToolNode, nodeList, appId } = useContextSelector(
    WorkflowContext,
    (v) => v,
  );

  const { data: members = [] } = useRequest2(loadAndGetTeamMembers, {
    manual: true,
  });

  const [templateType, setTemplateType] = useState(TemplateTypeEnum.basic);

  const { data: basicNodes } = useRequest2(
    async () => {
      if (templateType === TemplateTypeEnum.basic) {
        return basicNodeTemplates
          .filter((item) => {
            // unique node filter
            if (item.unique) {
              const nodeExist = nodeList.some((node) => node.flowNodeType === item.flowNodeType);
              if (nodeExist) {
                return false;
              }
            }
            // tool stop or tool params
            if (
              !hasToolNode &&
              (item.flowNodeType === FlowNodeTypeEnum.stopTool ||
                item.flowNodeType === FlowNodeTypeEnum.toolParams)
            ) {
              return false;
            }
            return true;
          })
          .map<NodeTemplateListItemType>((item) => ({
            id: item.id,
            flowNodeType: item.flowNodeType,
            templateType: item.templateType,
            avatar: item.avatar,
            name: item.name,
            intro: item.intro,
          }));
      }
    },
    {
      manual: false,
      throttleWait: 100,
      refreshDeps: [basicNodeTemplates, nodeList, hasToolNode, templateType],
    },
  );
  const {
    data: teamAndSystemApps,
    loading: isLoading,
    runAsync: loadNodeTemplates,
  } = useRequest2(
    async ({
      parentId = '',
      type = templateType,
      searchVal = searchKey,
    }: {
      parentId?: ParentIdType;
      type?: TemplateTypeEnum;
      searchVal?: string;
    }) => {
      if (type === TemplateTypeEnum.teamPlugin || type === TemplateTypeEnum.basic) {
        const teamApps = await appService
          .getTeamAppTemplates()
          .then((res) => res.filter((app) => app.id !== appId));

        return teamApps.map<NodeTemplateListItemType>((app) => {
          const member = members.find((member) => member.tmbId === app.tmbId);
          return {
            ...app,
            author: member?.memberName,
            authorAvatar: member?.avatar,
            templateType: FlowNodeTemplateTypeEnum.tools,
          };
        });
      }

      // if (type === TemplateTypeEnum.mcp) {
      //   const mcp = await mcpService.getMcpList({ page: 1, pageSize: 100 });
      //   return mcp.list;
      // }

      if (type === TemplateTypeEnum.systemPlugin) {
        return localPluginModules;
      }
    },
    {
      onSuccess(res, [{ parentId = '', type = templateType }]) {
        setParentId(parentId);
        setTemplateType(type);
      },
      refreshDeps: [members, searchKey, templateType],
    },
  );

  const templates = useMemo(
    () => [...(basicNodes ?? []), ...(teamAndSystemApps ?? [])],
    [basicNodes, teamAndSystemApps],
  );

  // Get paths
  const { data: paths = [] } = useRequest2(
    () => {
      if (templateType === TemplateTypeEnum.teamPlugin)
        return appService.getAppFolderPath(parentId);
      return pluginService.getSystemPluginPaths(parentId);
    },
    {
      manual: false,
      refreshDeps: [parentId],
    },
  );

  const onUpdateParentId = useCallback(
    (parentId: ParentIdType) => {
      loadNodeTemplates({
        parentId,
      });
    },
    [loadNodeTemplates],
  );

  // Init load refresh templates
  useRequest2(
    () =>
      loadNodeTemplates({
        parentId: '',
        searchVal: searchKey,
      }),
    {
      manual: false,
      throttleWait: 300,
      refreshDeps: [searchKey],
    },
  );

  const Render = useMemo(() => {
    return (
      <div className="flex max-h-[600px] select-none flex-col overflow-hidden">
        {/* Header */}
        <div className="flex h-[50px] flex-col">
          {/* Tabs */}
          <div>
            <Segmented
              block
              options={[
                {
                  label: t('core.module.template.Basic Node'),
                  value: TemplateTypeEnum.basic,
                },
                {
                  label: t('core.module.template.Plugin'),
                  value: TemplateTypeEnum.systemPlugin,
                },
                {
                  label: t('core.module.template.mcp'),
                  value: TemplateTypeEnum.mcp,
                },
              ]}
              style={{
                backgroundColor: 'white',
              }}
              width="100%"
              value={templateType}
              onChange={(e) => {
                loadNodeTemplates({
                  type: e as TemplateTypeEnum,
                  parentId: '',
                });
              }}
              className="custom-segmented"
            />
          </div>
        </div>
        <div className="max-h-[540px] w-[576px]">
          {' '}
          <RenderList
            templates={templates}
            type={templateType}
            parentId={parentId}
            setParentId={onUpdateParentId}
            connectParams={connectParams}
          />
        </div>
      </div>
    );
  }, [templateType, templates, parentId, onUpdateParentId, connectParams, loadNodeTemplates]);

  return Render;
};

export default React.memo(NodeTemplatesModal);

const RenderList = React.memo(function RenderList({
  templates,
  type,
  // onClose,
  parentId,
  setParentId,
  connectParams,
}: RenderListProps) {
  const { setLoading } = useSystemStore();

  const { isPc } = useWindowWidth();
  const isSystemPlugin = type === TemplateTypeEnum.systemPlugin;

  const { screenToFlowPosition } = useReactFlow();
  const { reactFlowWrapper, setNodes, nodeList, setEdges } = useContextSelector(
    WorkflowContext,
    (v) => v,
  );
  const { computedNewNodeName } = useWorkflowUtils();

  const formatTemplates = useMemo<NodeTemplateListType>(() => {
    const copy: NodeTemplateListType = cloneDeep(workflowNodeTemplateList);
    //
    templates.forEach((item) => {
      const index = copy.findIndex((template) => template.type === item.templateType);
      if (index === -1) return;
      copy[index].list.push(item);
    });
    return copy.filter((item) => item.list.length > 0);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [templates, parentId]);

  const onAddNode = useCallback(
    async ({
      template,
      position,
      isDarg = false,
    }: {
      template: NodeTemplateListItemType;
      position: XYPosition;
      isDarg?: boolean;
    }) => {
      if (!reactFlowWrapper?.current) return;

      // Load template node

      const templateNode = await (async () => {
        try {
          if (
            template.flowNodeType === FlowNodeTypeEnum.tool ||
            template.flowNodeType === FlowNodeTypeEnum.toolSet
          ) {
            return {
              ...template,
              name: t(template.name as any),
            };
          }
          // get plugin preview module
          if (
            // template.flowNodeType === FlowNodeTypeEnum.pluginModule ||
            template.flowNodeType === FlowNodeTypeEnum.appModule
          ) {
            setLoading(true);
            const res = await pluginService.getPreviewPluginNode({ appId: template.id });
            setLoading(false);
            return {
              ...res,
              name: t(template.name as any),
            };
          }

          // base node
          const baseTemplate = moduleTemplatesFlat.find((item) => item.id === template.id);
          if (!baseTemplate) {
            throw new Error('baseTemplate not found');
          }
          return { ...baseTemplate };
        } catch (e) {
          message.error(getErrText(e, t('core.plugin.Get Plugin Module Detail Failed')));
          setLoading(false);
          return Promise.reject(e);
        }
      })();

      const nodePosition = screenToFlowPosition(position);
      const mouseX = nodePosition.x - 100;
      const mouseY = nodePosition.y - 20;

      // Add default values to some inputs
      const defaultValueMap: Record<string, any> = {
        [NodeInputKeyEnum.userChatInput]: undefined,
      };
      nodeList.forEach((node) => {
        if (node.flowNodeType === FlowNodeTypeEnum.workflowStart) {
          defaultValueMap[NodeInputKeyEnum.userChatInput] = [
            node.nodeId,
            NodeOutputKeyEnum.userChatInput,
          ];
        }
      });

      const newNode = nodeTemplate2FlowNode({
        template: {
          ...templateNode,
          isFolded: false,
          name: computedNewNodeName({
            templateName: t(templateNode.name as any),
            flowNodeType: templateNode.flowNodeType,
            pluginId: templateNode.pluginId,
          }),
          intro: t(templateNode.intro as any),
          inputs: (templateNode as any).inputs?.map((input: FlowNodeInputItemType) => ({
            ...input,
            value: defaultValueMap[input.key] ?? input.value,
            valueDesc: t(input.valueDesc as any),
            label: t(input.label as any),
            description: t(input.description as any),
            debugLabel: t(input.debugLabel as any),
            toolDescription: t(input.toolDescription as any),
          })),
          outputs: (templateNode as any).outputs.map((output: FlowNodeOutputItemType) => ({
            ...output,
            valueDesc: t(output.valueDesc as any),
            label: t(output.label as any),
            description: t(output.description as any),
          })),
        },
        position: { x: mouseX, y: mouseY },
        selected: true,
        t,
      });
      const newNodes = [newNode];

      if (templateNode.flowNodeType === FlowNodeTypeEnum.loop) {
        const startNode = nodeTemplate2FlowNode({
          template: LoopStartNode,
          position: { x: mouseX + 60, y: mouseY + 280 },
          parentNodeId: newNode.id,
          t,
        });
        const endNode = nodeTemplate2FlowNode({
          template: LoopEndNode,
          position: { x: mouseX + 420, y: mouseY + 680 },
          parentNodeId: newNode.id,
          t,
        });

        newNodes.push(startNode, endNode);
      }

      // edges自动连接
      // const edges = newNodes.map((node) => ({
      //   source: node.id,
      //   target: node.id,
      // }));

      setNodes((state) => {
        const newState = state
          .map((node) => ({
            ...node,
            selected: false,
          }))
          // @ts-ignore
          .concat(newNodes);
        return newState;
      });

      if (!connectParams) return;
      const isToolHandle = connectParams?.handleId === 'selectedTools';

      const newEdges = newNodes
        .filter((node) => {
          // Exclude nodes that don't meet the conditions
          // 1. Tool set nodes must be connected through tool handle
          if (!isToolHandle && node.data.flowNodeType === FlowNodeTypeEnum.toolSet) {
            return false;
          }

          // 2. Exclude loop start and end nodes
          if (
            [FlowNodeTypeEnum.loopStart, FlowNodeTypeEnum.loopEnd].includes(node.data.flowNodeType)
          ) {
            return false;
          }

          // 3. Tool handle can only connect to tool nodes
          if (isToolHandle && !node.data.isTool) {
            return false;
          }

          return true;
        })
        .map((node) => ({
          id: getNanoid(),
          source: connectParams.nodeId as string,
          sourceHandle: connectParams.handleId,
          target: node.id,
          targetHandle: isToolHandle ? 'selectedTools' : `${node.id}-target-left`,
          type: 'default',
        }));

      setEdges((state) => {
        const newState = state.concat(newEdges);
        return newState;
      });
    },
    [
      reactFlowWrapper,
      screenToFlowPosition,
      nodeList,
      computedNewNodeName,
      setNodes,
      setLoading,
      connectParams,
      setEdges,
    ],
  );

  // 简化渲染逻辑，减少嵌套
  if (type === TemplateTypeEnum.mcp) {
    return <McpListRender onAddNode={onAddNode} />;
  }

  if (templates.length === 0) {
    return (
      <div className="flex h-full items-center justify-center">
        <EmptyTip text={t('module.No Modules')} />
      </div>
    );
  }

  if (type === TemplateTypeEnum.basic) {
    return renderBasicContent(type, formatTemplates, isPc, onAddNode);
  }

  return <TeamPluginList isPc={isPc} onAddNode={onAddNode} />;
});
